#pragma once
#include <iostream>
#include <string>
using namespace std;

// 模拟定协议与处理

namespace protocol
{

    const string sepa = " ";
    const string line_break = "\r\n"; // linux换行默认是\r\n

    // ***添加报头数据和解报头
    void Encode(string &mes)
    {
        int len = mes.size();
        string ret = to_string(len) + line_break + mes + line_break;
        mes = ret;
    }

    // 一次解包的过程
    bool Decode(string &package, string &ret)
    {
        //"len\n123wuwu\n"
        // 先判断收到的数据是否完整
        int len = package.size();
        int pos = package.find(line_break); // 指向第一个换行符
        if (pos == string::npos)
            return false;

        int pos1 = package.find(line_break, pos + line_break.size()); // 指向第二个换行符
        if (pos1 == string::npos)
            return false;

        // 解包后的数据
        ret = package.substr(pos + line_break.size(), pos1 - pos - 1);
        // 去掉package中完整报文的数据部分
        package = package.substr(pos1 + line_break.size());

        return true;
    }

    // 协议请求
    class Request
    {
        friend class Cal;

    public:
        Request() {}
        Request(int x, int y, char op)
            : _x(x), _y(y), _oper(op)
        {
        }

        void info()
        {
            cout << _x << ' ' << _oper << ' ' << _y << " = ?" << endl;
        }

        void Serialize(string &out) // 序列化
        {
            out = to_string(_x) + sepa + _oper + sepa + to_string(_y);
        }

        //"x + y"
        void Deserialize(const string s) // 反序列化
        {

            int begin = 0;
            int end = s.find(sepa, begin);
            _x = stoi(s.substr(begin, end - begin));
            begin = end + sepa.size(); // 加的1其实就是' '的长度

            end = s.find(sepa, begin);
            _oper = s.substr(begin, end - begin)[0];
            begin = end + sepa.size();

            _y = stoi(s.substr(begin));
        }

        int GetX() { return _x; };
        int GetY() { return _y; };
        char GetOper() { return _oper; };

    private:
        int _x;
        int _y;
        char _oper;
    };

    // 协议响应
    class Response
    {
    public:
        Response()
        {
        }
        Response(int re, string ret_info)
            : _result(re), _ret_info(ret_info)
        {
        }
        void Info()
        {
            cout << "result = " << _result << " (" << _ret_info << ')' << endl;
        }

        void Serialize(string &out) // 序列化
        {
            out = to_string(_result) + sepa + _ret_info;
        }

        //"_result _ret_info"
        void Deserialize(const string s) // 反序列化
        {

            int begin = 0;
            int end = s.find(sepa, begin);
            _result = stoi(s.substr(begin, end - begin));
            begin = end + sepa.size(); // 加的1其实就是分隔符的长度

            _ret_info = s.substr(begin);
        }

    private:
        int _result;      // 保存结果
        string _ret_info; // 结果信息
    };

    // 创建请求、响应对象的工厂
    class Factor
    {
    public:
        static shared_ptr<Request> BuildRequest()
        {
            shared_ptr<Request> reqs = make_shared<Request>();
            return reqs;
        }
        static shared_ptr<Request> BuildRequest(int x, int y, char op)
        {
            shared_ptr<Request> reqs = make_shared<Request>(x, y, op);
            return reqs;
        }

        static shared_ptr<Response> BuildResponse()
        {
            shared_ptr<Response> reps = make_shared<Response>();
            return reps;
        }
        static shared_ptr<Response> BuildResponse(int re, string ret_info)
        {
            shared_ptr<Response> reps = make_shared<Response>(re, ret_info);
            return reps;
        }
    };
};